/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package actioncombination.logic.rlmethod;

import actioncombination.common.datastructure.Pair;
import actioncombination.common.value.DoubleValue;
import actioncombination.common.value.Value;
import actioncombination.logic.agent.action.Action;
import actioncombination.logic.agent.AgentState;
import actioncombination.logic.agent.knowledge.*;
import actioncombination.logic.agent.RLAgent;
import actioncombination.problem.gridworld.AgentStateImpl;
import actioncombination.logic.environment.RLEnvironment;
import actioncombination.logic.policy.PolicyStrategy;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

/**
 *
 * @author Administrador
 */
public class Sarsa extends RLMethodStrategy{

    private Action action;
    
    public Sarsa(PolicyStrategy polStrategy) {
        super(polStrategy);
    }

    @Override
    public void beginEpisode(RLAgent agent) {
        AgentStateImpl state= (AgentStateImpl) agent.getAgentState();
        this.setAction(init(agent));
        while(!agent.getGoal().isGoalState(state)){
            step(agent,this.getAction());
        }
        endEpisode();
    }
  
    private Action init(RLAgent agent){
        AgentStateImpl state= (AgentStateImpl) agent.getAgentState();

        state.initState();
        //cargo en valuesStates las posibles acciones que puedo tomar
        //y los estados hacia los que me llevan
        Map<Action,Value> valuesStates=agent.getAgentState().getActionValues();
        //elijo la accion dada por la politica para el estado actual
        return this.getPolStrategy().selectAction(valuesStates);
    }    
    
    //REVISAR
    private void step(RLAgent agent, Action a) {
        AgentStateImpl oldState= (AgentStateImpl)agent.getAgentState();
        //ejecito la accion y observo el nuevo estado 
        AgentStateImpl newState= (AgentStateImpl)agent.execute(a);
        //observo la recompensa del nuevo estado
        DoubleValue reward=((RLEnvironment)agent.getEnvironment()).getReward(agent);
        //cargo en valuesStates las posibles acciones que puedo tomar
        //y los estados hacia los que me llevan
        Map<Action,Value> valuesStates=agent.getAgentState().getActionValues();
        //elijo la accion dada por la politica para el estado actual
        Action aPrima=this.getPolStrategy().selectAction(valuesStates);              
        //actualizo el viejo estado con la formula de actualizacion
        agent.update(oldState, newState, a, aPrima,
                this.getLearningStep(), reward, this.getDiscountRate());
        //actualizo la accion elegida
        this.setAction(aPrima);
    }

    @Override
    public void endEpisode() {
        
    }

    private Action getAction() {
        return action;
    }

    private void setAction(Action action) {
        this.action = action;
    }

    
}
